import 'dart:convert';
import 'dart:typed_data';
import 'package:web_socket_channel/io.dart';
import 'package:xftpdemo/ise/bean/ise_response_data_entity.dart';
import 'package:xftpdemo/ise/generated/json/ise_response_data_entity_helper.dart';
import 'xf_ise_utils.dart';

/**
 * author：twopai
 * email：twopai@hotmail.com
 * des：语音测评管理类
 * time：2022/02/16
 */
class XfIseManage {
  static final frameSize = 1280;
  static const int intervel = 40;
  static const statusInitFrame = -1;
  static const statusFirstFrame = 0;
  static const statusContinueFrame = 1;
  static const statusLastFrame = 2;

  String _host;
  String _appId;
  String _apiKey;
  String _apiSecret;
  IOWebSocketChannel _channel;
  int _status = statusFirstFrame;
  String checkTxt = '语音测评';
  bool isChinese=true;

  ///关闭连接
  close() {
    log('关闭连接');
    _channel?.sink.close();
  }

  //设置测评文本
  XfIseManage.setCheckTxt({String checkTxt}){
    this.checkTxt=checkTxt;
  }
  /// 创建连接
  /// data 需要转化的音频的字节数组
  /// listen 转化完成后的回调
  XfIseManage.connect(this._host, this._apiKey, this._apiSecret, this._appId,
      List<int> data, void Function(String msg) listen) {
    log('创建连接');
    _channel?.sink?.close();
    var iseAuthUrl = getIseAuthUrl(_host, _apiKey, _apiSecret);
    print('iseAuthUrl=$iseAuthUrl');
    _channel = IOWebSocketChannel.connect(iseAuthUrl);
    //创建监听
    _channel?.stream.listen((event) {
        // log('_channel-->listen event=$event');
        _onEvent(event, listen);
      },onError:(event){
        // log('_channel-->onError event=$event');
      },onDone: (){
        log('_channel-->onDone');
      }
    );
    //语音转文字
    _initSend(data);
  }

  void _onEvent(dynamic data, void Function(String msg) listen) {
    Map<String,dynamic> map = json.decode(data);
    final resp = IseResponseData();
    // log('_onOpen-->map=$map');
    iseResponseDataFromJson(resp, map);
    //识别失败
    if (resp.code != 0) {
      log('code:${resp.code} error:${resp.message} sid:${resp.sid}');
      return;
    }
    if (resp.data != null) {
      //中间识别结果
      if (resp.data?.data != null) {
        final msg = resp.data?.data;
        if(msg!=null){
        }
        log('中间识别结果:$msg');
      }
      //说明数据全部返回完毕，可以关闭连接，释放资源
      if (resp.data?.status == 2) {
        // _end = DateTime.now();
        // log('总共耗时:${_end.difference(_start).inMilliseconds}');
        print('获取识别结果-->status=${resp.data?.status},data=${resp.data?.data}');
        // _decoder.decode(resp.data?.data);
        Uint8List decode = base64.decode(resp.data?.data);
        String decodestr = utf8.decode(decode);
        print('获取识别结果-->decodestr=:${decodestr}');
        // _translate(decode);
        listen(decodestr);
      }
    }
  }
  _initSend(List<int> bytes){
    // _start = DateTime.now();
    //先发送初始参数 ssb
    Future.delayed(Duration(milliseconds: intervel), () {
      _send('', statusInitFrame);
    });
    if (!(bytes is Uint8List)) {
      bytes = Uint8List.fromList(bytes);
    }
    int count = 0;
    final l = bytes.length % frameSize;
    if (l > 0) {
      count = (bytes.length / frameSize + 1).toInt();
    } else {
      count = bytes.length ~/ frameSize;
    }
    log('count = $count');
    for (int i = 0; i < count; i++) {
      List<int> len;
      if (i == count - 1) {
        len = bytes.sublist(i * frameSize);
      } else {
        len = bytes.sublist(i * frameSize, (i + 1) * frameSize);
      }
      String msg;
      if (len.isEmpty) {
        msg = '';
      } else {
        msg = base64.encode(len);
      }

      //第一帧和中间帧
      Future.delayed(Duration(milliseconds: intervel), () {
        _send(msg, _status);
      });
    }
    //最后一帧
    Future.delayed(Duration(milliseconds: intervel), () {
      _send('', statusLastFrame);
    });
  }


  ///向服务器发送数据
  void _send(String msg, int status) {
    switch (status) {
      case statusInitFrame: // 发送初始参数status = -1
        Map frame = new Map();
        Map common = new Map(); //第一帧必须发送
        Map business = new Map(); //第一帧必须发送

        Map data = new Map(); //每一帧都要发送

        //填充common
        common['app_id'] = _appId;
        //填充business
        business['category'] = 'read_sentence';
        business['rstcd'] = 'utf8';
        business['sub'] = 'ise';
        business['ent'] = '${(isChinese??true)?'cn_vip':'en_vip'}';
        business['tte'] = 'utf-8';
        business['cmd'] = 'ssb';
        business['auf'] = 'audio/L16;rate=16000';
        business['aue'] = 'raw';
        business['text'] = '\uFEFF'+checkTxt;

        //填充data
        data['status'] = statusFirstFrame;
        data['data'] = '';


        //填充frame
        frame['common'] = common;
        frame['business'] = business;
        frame['data'] = data;
        _sendMessage(json.encode(frame));
        _status = statusFirstFrame; // 发送完初始帧改变status 为 0
        log('send init');//做到此处
        break;
      case statusFirstFrame: // 第一帧音频status = 0
        Map frame = new Map();
        Map business = new Map(); //第一帧必须发送
        Map data = new Map(); //每一帧都要发送

        //填充business
        business['cmd'] = 'auw';
        business['aus'] = 1;
        business['aue'] = 'raw';
        //填充data
        data['status'] = 1;
        data['data'] = msg;
        data['data_type'] = 1;
        data['encoding'] = 'raw';
        //填充frame
        frame['business'] = business;
        frame['data'] = data;

        _sendMessage(json.encode(frame));
        _status = statusContinueFrame; // 发送完第一帧改变status 为 1
        log('send first');
        break;

      case statusContinueFrame: //中间帧status = 1
        Map frame = new Map();
        Map business = new Map(); //第一帧必须发送
        Map data = new Map(); //每一帧都要发送

        //填充business
        business['cmd'] = 'auw';
        business['aus'] = 2;
        business['aue'] = 'raw';
        //填充data
        data['status'] = 1;
        data['data'] = msg;
        data['data_type'] = 1;
        data['encoding'] = 'raw';
        //填充frame
        frame['business'] = business;
        frame['data'] = data;
        _sendMessage(json.encode(frame));
        log('send continue');
        break;

      case statusLastFrame: // 最后一帧音频status = 2 ，标志音频发送结束
        Map frame = new Map();
        Map business = new Map(); //第一帧必须发送
        Map data = new Map(); //每一帧都要发送

        //填充business
        business['cmd'] = 'auw';
        business['aus'] = 4;
        business['aue'] = 'raw';
        //填充data
        data['status'] = 2;
        data['data'] = '';
        data['data_type'] = 1;
        data['encoding'] = 'raw';
        //填充frame
        frame['business'] = business;
        frame['data'] = data;
        _sendMessage(json.encode(frame));
        log('send last');
        _status = statusFirstFrame;
        log('所有数据都已发送');
        break;
    }
  }

  void _sendMessage(dynamic data) {
    // print('_sendMessage-->data=$data');
    _channel?.sink?.add(data);
  }
}
bool isDebug = false;

///日志
log(dynamic msg) {
  print('$msg');
}
